import socket
import requests
import time
from typing import Dict, Optional
from src.models.models import SystemConfig

class NetworkInfoService:
    """网络信息服务"""
    
    @staticmethod
    def get_local_ip() -> str:
        """获取本地IP地址"""
        try:
            # 方法1: 使用socket.gethostname()获取主机名，然后获取IP
            hostname = socket.gethostname()
            local_ip = socket.gethostbyname(hostname)
            
            # 验证获取的IP是否为有效的本地IP
            if NetworkInfoService._is_valid_local_ip(local_ip):
                return local_ip
            
            # 方法2: 如果方法1失败，尝试获取所有网络接口的IP
            for interface_name in socket.if_nameindex():
                try:
                    # 获取网络接口的IP地址
                    interface_ip = socket.inet_ntoa(socket.inet_aton(socket.gethostbyname(interface_name[1])))
                    if NetworkInfoService._is_valid_local_ip(interface_ip):
                        return interface_ip
                except:
                    continue
            
            # 方法3: 如果上述方法都失败，使用备用方法
            try:
                # 绑定到本地回环地址，然后获取本地IP
                with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as s:
                    s.bind(('', 0))
                    local_ip = s.getsockname()[0]
                    if NetworkInfoService._is_valid_local_ip(local_ip):
                        return local_ip
            except:
                pass
            
            return "获取失败"
            
        except Exception as e:
            print(f"获取本地IP失败: {str(e)}")
            return "获取失败"
    
    @staticmethod
    def get_public_ip() -> str:
        """获取公网IP地址"""
        try:
            # 使用多个IP查询服务，提高成功率
            ip_services = [
                "https://ipinfo.io/ip",
                "https://icanhazip.com",
                "https://httpbin.org/ip"
            ]
            
            for service in ip_services:
                try:
                    response = requests.get(service, timeout=5)
                    if response.status_code == 200:
                        # 清理响应内容，只保留IP地址
                        ip = response.text.strip()
                        # 验证IP格式
                        if NetworkInfoService._is_valid_ip(ip):
                            return ip
                except Exception:
                    continue
            
            return "获取失败"
        except Exception as e:
            print(f"获取公网IP失败: {str(e)}")
            return "获取失败"
    
    @staticmethod
    def get_network_status() -> str:
        """获取网络状态"""
        try:
            # 尝试获取公网IP来判断网络状态
            public_ip = NetworkInfoService.get_public_ip()
            if public_ip != "获取失败" and NetworkInfoService._is_valid_ip(public_ip):
                return "正常"
            else:
                return "异常"
        except Exception:
            return "异常"
    
    @staticmethod
    def get_port() -> str:
        """获取端口号（从system_config表中获取）"""
        try:
            port = SystemConfig.get_config('port', '5000')
            return str(port) if port is not None else '5000'
        except Exception as e:
            print(f"获取端口失败: {str(e)}")
            return "获取失败"
    
    @staticmethod
    def get_all_network_info() -> Dict[str, str]:
        """获取所有网络信息"""
        return {
            'local_ip': NetworkInfoService.get_local_ip(),
            'public_ip': NetworkInfoService.get_public_ip(),
            'network_status': NetworkInfoService.get_network_status(),
            'port': NetworkInfoService.get_port()
        }
    
    @staticmethod
    def _is_valid_ip(ip: str) -> bool:
        """验证IP地址格式"""
        try:
            parts = ip.split('.')
            if len(parts) != 4:
                return False
            for part in parts:
                if not part.isdigit() or not 0 <= int(part) <= 255:
                    return False
            return True
        except:
            return False
    
    @staticmethod
    def _is_valid_local_ip(ip: str) -> bool:
        """验证是否为有效的本地IP地址"""
        try:
            if not NetworkInfoService._is_valid_ip(ip):
                return False
            
            # 排除回环地址
            if ip == "127.0.0.1" or ip.startswith("127."):
                return False
            
            # 排除特殊地址
            if ip == "0.0.0.0" or ip == "255.255.255.255":
                return False
            
            # 检查是否为私有IP地址范围
            parts = ip.split('.')
            first_octet = int(parts[0])
            second_octet = int(parts[1])
            
            # 私有IP地址范围：
            # 10.0.0.0 - 10.255.255.255
            # 172.16.0.0 - 172.31.255.255  
            # 192.168.0.0 - 192.168.255.255
            if (first_octet == 10 or
                (first_octet == 172 and 16 <= second_octet <= 31) or
                (first_octet == 192 and second_octet == 168)):
                return True
            
            return False
        except:
            return False 